/**
 * Copyright 2018-2019 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.modulelink.config;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import com.jianggujin.modulelink.action.JAction;
import com.jianggujin.modulelink.exception.JModuleLinkException;
import com.jianggujin.modulelink.module.JModuleListener;
import com.jianggujin.modulelink.support.plugin.JInterceptor;
import com.jianggujin.modulelink.util.JAssert;

/**
 * 模块配置信息
 * 
 * @author jianggujin
 *
 */
public class JModuleConfig implements Comparable<JModuleConfig> {
    /**
     * 模块名,建议用英文命名
     */
    private final String moduleName;

    /**
     * 模块描述
     */
    private String description;

    /**
     * JAR 包资源地址,模块存放的地方
     */
    private Set<URL> moduleUrls;

    /**
     * 需要排除的Action
     */
    private Set<String> exclusionActions;

    /**
     * 扫描包
     * <p>
     * 普通模式自动扫描包下面的{@link JAction}、和{@link JModuleListener}、和{@link JInterceptor}
     * </p>
     * <p>
     * 如果使用Spring配置且模块环境为Spring，该值为空时，尝试使用XML加载，否则使用注解
     * </p>
     * <p>
     * 在SpringBoot模块环境下该值无效
     * </p>
     */
    private Set<String> scanPackages;
    /**
     * 模块加载策略
     */
    private JModuleLoadPolicy moduleLoadPolicy;
    /**
     * 需要排除的模块监听器
     */
    private Set<String> exclusionModuleListeners;
    /**
     * 需要排除的拦截器
     */
    private Set<String> exclusionInterceptors;
    /**
     * 是否激活
     */
    private boolean active = true;

    public JModuleConfig(String moduleName) {
        JAssert.checkNotNull(moduleName, "moduleName must not be null");
        this.moduleName = moduleName;
    }

    /**
     * 获得模块名称
     * 
     * @return 模块名称
     */
    public String getModuleName() {
        return moduleName;
    }

    /**
     * 获得模块描述
     * 
     * @return 模块描述
     */
    public String getDescription() {
        return description;
    }

    /**
     * 设置模块描述
     * 
     * @param description 模块描述
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * 获得模块地址
     * 
     * @return 模块地址
     */
    public Set<URL> getModuleUrls() {
        return moduleUrls;
    }

    /**
     * 设置模块地址
     * 
     * @param moduleUrls 模块地址
     */
    public void setModuleUrls(Set<URL> moduleUrls) {
        this.moduleUrls = moduleUrls;
    }

    /**
     * 添加模块地址
     * 
     * @param moduleUrl 模块地址
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addModuleUrl(URL moduleUrl) {
        JAssert.checkNotNull(moduleUrl, "moduleUrl must not be null");
        if (this.moduleUrls == null) {
            this.moduleUrls = new HashSet<URL>();
        }
        this.moduleUrls.add(moduleUrl);
        return this;
    }

    /**
     * 添加模块地址
     * 
     * @param moduleFile 模块地址
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addModuleUrl(File moduleFile) {
        JAssert.checkNotNull(moduleFile, "moduleFile must not be null");
        if (this.moduleUrls == null) {
            this.moduleUrls = new HashSet<URL>();
        }
        try {
            this.moduleUrls.add(moduleFile.toURI().toURL());
        } catch (MalformedURLException e) {
            throw new JModuleLinkException(e);
        }
        return this;
    }

    /**
     * 获得移除的Action
     * 
     * @return 移除的Action
     */
    public Set<String> getExclusionActions() {
        return exclusionActions;
    }

    /**
     * 设置移除的Action
     * 
     * @param exclusionActions 移除的Action
     */
    public void setExclusionActions(Set<String> exclusionActions) {
        this.exclusionActions = exclusionActions;
    }

    /**
     * 添加移除的Action
     * 
     * @param exclusionActions 移除的Action
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addExclusionActions(Collection<String> exclusionActions) {
        if (exclusionActions != null) {
            if (this.exclusionActions == null) {
                this.exclusionActions = new HashSet<String>();
            }
            this.exclusionActions.addAll(exclusionActions);
        }
        return this;
    }

    /**
     * 添加移除的Action
     * 
     * @param exclusionAction 移除的Action
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addExclusionAction(String exclusionAction) {
        JAssert.checkNotNull(exclusionAction, "exclusionAction must not be null");
        if (this.exclusionActions == null) {
            this.exclusionActions = new HashSet<String>();
        }
        this.exclusionActions.add(exclusionAction);
        return this;
    }

    /**
     * 获得扫描包的包名
     * 
     * @return 扫描包的包名
     */
    public Set<String> getScanPackages() {
        return scanPackages;
    }

    /**
     * 设置扫描包的包名
     * 
     * @param scanPackages 扫描包的包名
     */
    public void setScanPackages(Set<String> scanPackages) {
        this.scanPackages = scanPackages;
    }

    /**
     * 添加扫描包的包名
     * 
     * @param packageName 扫描包的包名
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addScanPackage(String packageName) {
        JAssert.checkNotNull(packageName, "packageName must not be null");
        if (this.scanPackages == null) {
            this.scanPackages = new HashSet<String>();
        }
        this.scanPackages.add(packageName);
        return this;
    }

    /**
     * 获得模块加载策略，默认{@link JModuleLoadPolicy#AbortPolicy}
     * 
     * @return
     */
    public JModuleLoadPolicy getModuleLoadPolicy() {
        if (this.moduleLoadPolicy == null) {
            return JModuleLoadPolicy.AbortPolicy;
        }
        return moduleLoadPolicy;
    }

    /**
     * 设置模块加载策略
     * 
     * @param moduleLoadPolicy
     */
    public void setModuleLoadPolicy(JModuleLoadPolicy moduleLoadPolicy) {
        this.moduleLoadPolicy = moduleLoadPolicy;
    }

    /**
     * 获得需要排除的模块监听器
     * 
     * @return 需要排除的模块监听器
     */
    public Set<String> getExclusionModuleListeners() {
        return exclusionModuleListeners;
    }

    /**
     * 设置需要排除的模块监听器
     * 
     * @param exclusionModuleListeners 需要排除的模块监听器
     */
    public void setExclusionModuleListeners(Set<String> exclusionModuleListeners) {
        this.exclusionModuleListeners = exclusionModuleListeners;
    }

    /**
     * 添加需要排除的模块监听器
     * 
     * @param exclusionModuleListener 需要排除的模块监听器
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addExclusionModuleListener(String exclusionModuleListener) {
        JAssert.checkNotNull(exclusionModuleListener, "exclusionModuleListener must not be null");
        if (this.exclusionModuleListeners == null) {
            this.exclusionModuleListeners = new HashSet<String>();
        }
        this.exclusionModuleListeners.add(exclusionModuleListener);
        return this;
    }

    /**
     * 获得需要排除的拦截器
     * 
     * @return 需要排除的拦截器
     */
    public Set<String> getExclusionInterceptors() {
        return exclusionInterceptors;
    }

    /**
     * 设置需要排除的拦截器
     * 
     * @param exclusionInterceptors 需要排除的拦截器
     */
    public void setExclusionInterceptors(Set<String> exclusionInterceptors) {
        this.exclusionInterceptors = exclusionInterceptors;
    }

    /**
     * 添加需要排除的拦截器
     * 
     * @param exclusionInterceptor 需要排除的拦截器
     * @return {@link JModuleConfig}
     */
    public JModuleConfig addExclusionInterceptor(String exclusionInterceptor) {
        JAssert.checkNotNull(exclusionInterceptor, "exclusionInterceptor must not be null");
        if (this.exclusionInterceptors == null) {
            this.exclusionInterceptors = new HashSet<String>();
        }
        this.exclusionInterceptors.add(exclusionInterceptor);
        return this;
    }

    /**
     * 是否默认激活
     * 
     * @return
     */
    public boolean isActive() {
        return active;
    }

    /**
     * 设置是否默认激活
     * 
     * @param active
     */
    public void setActive(boolean active) {
        this.active = active;
    }

    @Override
    public int compareTo(JModuleConfig other) {
        return this.moduleName.compareTo(other.moduleName);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((moduleName == null) ? 0 : moduleName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        JModuleConfig other = (JModuleConfig) obj;
        if (moduleName == null) {
            if (other.moduleName != null) {
                return false;
            }
        } else if (!moduleName.equals(other.moduleName)) {
            return false;
        }
        return true;
    }
}
